<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- 
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License. 
-->
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://struts.apache.org/css/default.css">
    <style type="text/css">
        .dp-highlighter {
            width:95% !important;
        }
    </style>
    <style type="text/css">
        .footer {
            background-image:      url('https://cwiki.apache.org/confluence/images/border/border_bottom.gif');
            background-repeat:     repeat-x;
            background-position:   left top;
            padding-top:           4px;
            color:                 #666;
        }
    </style>
    <link href='https://struts.apache.org/highlighter/style/shCoreStruts.css' rel='stylesheet' type='text/css' />
    <link href='https://struts.apache.org/highlighter/style/shThemeStruts.css' rel='stylesheet' type='text/css' />
    <script src='https://struts.apache.org/highlighter/js/shCore.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushPlain.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushXml.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJava.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJScript.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushGroovy.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushBash.js' type='text/javascript'></script>
    <script type="text/javascript">
        SyntaxHighlighter.defaults['toolbar'] = false;
        SyntaxHighlighter.all();
    </script>
    <script type="text/javascript" language="javascript">
        var hide = null;
        var show = null;
        var children = null;

        function init() {
            /* Search form initialization */
            var form = document.forms['search'];
            if (form != null) {
                form.elements['domains'].value = location.hostname;
                form.elements['sitesearch'].value = location.hostname;
            }

            /* Children initialization */
            hide = document.getElementById('hide');
            show = document.getElementById('show');
            children = document.all != null ?
                    document.all['children'] :
                    document.getElementById('children');
            if (children != null) {
                children.style.display = 'none';
                show.style.display = 'inline';
                hide.style.display = 'none';
            }
        }

        function showChildren() {
            children.style.display = 'block';
            show.style.display = 'none';
            hide.style.display = 'inline';
        }

        function hideChildren() {
            children.style.display = 'none';
            show.style.display = 'inline';
            hide.style.display = 'none';
        }
    </script>
    <title>Execute and Wait Interceptor</title>
</head>
<body onload="init()">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
    <tr class="topBar">
        <td align="left" valign="middle" class="topBarDiv" align="left" nowrap>
            &nbsp;<a href="home.html">Home</a>&nbsp;&gt;&nbsp;<a href="guides.html">Guides</a>&nbsp;&gt;&nbsp;<a href="core-developers-guide.html">Core Developers Guide</a>&nbsp;&gt;&nbsp;<a href="interceptors.html">Interceptors</a>&nbsp;&gt;&nbsp;<a href="execute-and-wait-interceptor.html">Execute and Wait Interceptor</a>
        </td>
        <td align="right" valign="middle" nowrap>
            <form name="search" action="https://www.google.com/search" method="get">
                <input type="hidden" name="ie" value="UTF-8" />
                <input type="hidden" name="oe" value="UTF-8" />
                <input type="hidden" name="domains" value="" />
                <input type="hidden" name="sitesearch" value="" />
                <input type="text" name="q" maxlength="255" value="" />
                <input type="submit" name="btnG" value="Google Search" />
            </form>
        </td>
    </tr>
</table>

<div id="PageContent">
    <div class="pageheader" style="padding: 6px 0px 0px 0px;">
        <!-- We'll enable this once we figure out how to access (and save) the logo resource -->
        <!--img src="/wiki/images/confluence_logo.gif" style="float: left; margin: 4px 4px 4px 10px;" border="0"-->
        <div style="margin: 0px 10px 0px 10px" class="smalltext">Apache Struts 2 Documentation</div>
        <div style="margin: 0px 10px 8px 10px"  class="pagetitle">Execute and Wait Interceptor</div>

        <div class="greynavbar" align="right" style="padding: 2px 10px; margin: 0px;">
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14318">
                <img src="https://cwiki.apache.org/confluence/images/icons/notep_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Edit Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14318">Edit Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">
                <img src="https://cwiki.apache.org/confluence/images/icons/browse_space.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Browse Space"></a>
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">Browse Space</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14318">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_page_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14318">Add Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14318">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_blogentry_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add News"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14318">Add News</a>
        </div>
    </div>

    <div class="pagecontent">
        <div class="wiki-content">
            <div id="ConfluenceContent"><p>
The ExecuteAndWaitInterceptor is great for running long-lived actions in the background while showing the user a nice
progress meter. This also prevents the HTTP request from timing out when the action takes more than 5 or 10 minutes.
</p>

<p></p><p> Using this interceptor is pretty straight forward. Assuming that you are including struts-default.xml, this
interceptor is already configured but is not part of any of the default stacks. Because of the nature of this
interceptor, it must be the <b>last</b> interceptor in the stack.
</p>

<p></p><p> This interceptor works on a per-session basis. That means that the same action name (myLongRunningAction, in the
above example) cannot be run more than once at a time in a given session. On the initial request or any subsequent
requests (before the action has completed), the <b>wait</b> result will be returned. <b>The wait result is
responsible for issuing a subsequent request back to the action, giving the effect of a self-updating progress
meter</b>.
</p>

<p></p><p> If no "wait" result is found, Struts will automatically generate a wait result on the fly. This result is
written in FreeMarker and cannot run unless FreeMarker is installed. If you don't wish to deploy with FreeMarker, you
must provide your own wait result. This is generally a good thing to do anyway, as the default wait page is very
plain.
</p>

<p></p><p>Whenever the wait result is returned, the <b>action that is currently running in the background will be placed on
top of the stack</b>. This allows you to display progress data, such as a count, in the wait page. By making the wait
page automatically reload the request to the action (which will be short-circuited by the interceptor), you can give
the appearance of an automatic progress meter.
</p>

<p></p><p>This interceptor also supports using an initial wait delay. An initial delay is a time in milliseconds we let the
server wait before the wait page is shown to the user. During the wait this interceptor will wake every 100 millis
to check if the background process is done premature, thus if the job for some reason doesn't take to long the wait
page is not shown to the user.
<br clear="none"> This is useful for e.g. search actions that have a wide span of execution time. Using a delay time of 2000
millis we ensure the user is presented fast search results immediately and for the slow results a wait page is used.
</p>

<p></p><p><b>Important</b>: Because the action will be running in a separate thread, you can't use ActionContext because it
is a ThreadLocal. This means if you need to access, for example, session data, you need to implement SessionAware
rather than calling ActionContext.getSession().
</p>

<p></p><p>The thread kicked off by this interceptor will be named in the form <b><u>actionName</u>BackgroundProcess</b>.
For example, the <i>search</i> action would run as a thread named <i>searchBackgroundProcess</i>.
</p>

<h2 id="ExecuteandWaitInterceptor-Parameters">Parameters</h2>


<p></p><ul></ul><p></p><ul><li>threadPriority (optional) - the priority to assign the thread. Default is <code>Thread.NORM_PRIORITY</code>.</li><li>delay (optional) - an initial delay in millis to wait before the wait page is shown (returning <code>wait</code> as result code). Default is no initial delay.</li><li>delaySleepInterval (optional) - only used with delay. Used for waking up at certain intervals to check if the background process is already done. Default is 100 millis.</li></ul><p></p>


<h2 id="ExecuteandWaitInterceptor-ExtendingtheInterceptor">Extending the Interceptor</h2>

<p></p><p>
If you wish to make special preparations before and/or after the invocation of the background thread, you can extend
the BackgroundProcess class and implement the beforeInvocation() and afterInvocation() methods. This may be useful
for obtaining and releasing resources that the background process will need to execute successfully. To use your
background process extension, extend ExecuteAndWaitInterceptor and implement the getNewBackgroundProcess() method.
</p>

<h2 id="ExecuteandWaitInterceptor-Examples">Examples</h2>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<script class="brush: xml; gutter: false; theme: Default" type="syntaxhighlighter"><![CDATA[
&lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
    &lt;interceptor-ref name=&quot;completeStack&quot;/&gt;
    &lt;interceptor-ref name=&quot;execAndWait&quot;/&gt;
    &lt;result name=&quot;wait&quot;&gt;longRunningAction-wait.jsp&lt;/result&gt;
    &lt;result name=&quot;success&quot;&gt;longRunningAction-success.jsp&lt;/result&gt;
&lt;/action&gt;

&lt;%@ taglib prefix=&quot;s&quot; uri=&quot;/struts&quot; %&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Please wait&lt;/title&gt;
    &lt;meta http-equiv=&quot;refresh&quot; content=&quot;5;url=&lt;s:url includeParams=&quot;all&quot; /&gt;&quot;/&gt;
  &lt;/head&gt;
  &lt;body&gt;
    Please wait while we process your request.
    Click &lt;a href=&quot;&lt;s:url includeParams=&quot;all&quot; /&gt;&quot;&gt;&lt;/a&gt; if this page does not reload automatically.
  &lt;/body&gt;
&lt;/html&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;u&gt;Example code2:&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;
This example will wait 2 second (2000 millis) before the wait page is shown to the user. Therefore
if the long process didn&#39;t last long anyway the user isn&#39;t shown a wait page.
&lt;/p&gt;

&lt;pre&gt;
&lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
    &lt;interceptor-ref name=&quot;completeStack&quot;/&gt;
    &lt;interceptor-ref name=&quot;execAndWait&quot;&gt;
        &lt;param name=&quot;delay&quot;&gt;2000&lt;param&gt;
    &lt;interceptor-ref&gt;
    &lt;result name=&quot;wait&quot;&gt;longRunningAction-wait.jsp&lt;/result&gt;
    &lt;result name=&quot;success&quot;&gt;longRunningAction-success.jsp&lt;/result&gt;
&lt;/action&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;u&gt;Example code3:&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;
This example will wait 1 second (1000 millis) before the wait page is shown to the user.
And at every 50 millis this interceptor will check if the background process is done, if so
it will return before the 1 second has elapsed, and the user isn&#39;t shown a wait page.
&lt;/p&gt;

&lt;pre&gt;
&lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
    &lt;interceptor-ref name=&quot;completeStack&quot;/&gt;
    &lt;interceptor-ref name=&quot;execAndWait&quot;&gt;
        &lt;param name=&quot;delay&quot;&gt;1000&lt;param&gt;
        &lt;param name=&quot;delaySleepInterval&quot;&gt;50&lt;param&gt;
    &lt;interceptor-ref&gt;
    &lt;result name=&quot;wait&quot;&gt;longRunningAction-wait.jsp&lt;/result&gt;
    &lt;result name=&quot;success&quot;&gt;longRunningAction-success.jsp&lt;/result&gt;
&lt;/action&gt;
&lt;/pre&gt;

]]></script>
</div></div></div>
        </div>

        
    </div>
</div>
<div class="footer">
    Generated by CXF SiteExporter
</div>
</body>
</html>
